namespace FluentMvc
{
    using System;
    using System.Collections.Generic;
    using System.Linq.Expressions;
    using System.Web.Mvc;
    using Validations;

    public class StringRulesConfiguration<TModel> : RuleConfigurator<TModel,string,StringRulesConfiguration<TModel>> where TModel : class
    {
        internal StringRulesConfiguration(Expression<Func<TModel, string>> selector, ModelContext<TModel> context) : base(selector,context)
        {
            Child = this;
        }

        public StringRulesConfiguration<TModel> Min(int min,Action<RuleInitializer<TModel,string>> configuration = null)
        {
            var validationRule = new ModelClientValidationRule {ValidationType = "length"};
            validationRule.ValidationParameters.Add("min", min);
            var rule = new ValidationSetting<TModel>
            {
                CustomValidation = model => PropertySelector(model).Length >= min,
                PropertyName = PropertyName,
                ClientValidationRules = new List<ModelClientValidationRule>{validationRule}
            };
            ModelContext.GetSettings(PropertyName).ValidationSettings.Add(RunConfiguration(configuration, rule));
            return this;
        }

        public StringRulesConfiguration<TModel> Max(int max, Action<RuleInitializer<TModel, string>> configuration = null)
        {
            var validationRule = new ModelClientValidationRule { ValidationType = "length" };
            validationRule.ValidationParameters.Add("min", max);
            var rule = new ValidationSetting<TModel>
                           {
                               CustomValidation = model => PropertySelector(model).Length <= max,
                               PropertyName = PropertyName,
                               ClientValidationRules = new List<ModelClientValidationRule>{validationRule}
                           };
            ModelContext.GetSettings(PropertyName).ValidationSettings.Add(RunConfiguration(configuration, rule));
            return this;
        }

        public StringRulesConfiguration<TModel> Length(int min, int max, Action<RuleInitializer<TModel, string>> configuration = null)
        {
            var validationRule = new ModelClientValidationRule { ValidationType = "length" };
            validationRule.ValidationParameters.Add("min", min);
            validationRule.ValidationParameters.Add("max", max);
            var rule = new ValidationSetting<TModel>
                           {
                               CustomValidation = model =>
                                                  {
                                                      var value = PropertySelector(model);
                                                      if (value == null || value.Length < min || value.Length > max)
                                                          return false;
                                                      return true;
                                                  },
                               PropertyName = PropertyName,
                               ClientValidationRules = new List<ModelClientValidationRule>{validationRule}
                           };
            ModelContext.GetSettings(PropertyName).ValidationSettings.Add(RunConfiguration(configuration, rule));
            return Child;
        }

        public StringRulesConfiguration<TModel> Url(Action<RuleInitializer<TModel, string>> configuration = null)
        {
            var rule = new ValidationSetting<TModel>
            {
                Rule = new RegExValidator
                {
                    Pattern = @"((https?|ftp|gopher|telnet|file|notes|ms-help):((//)|(\\\\))+[\w\d:#@%/;$()~_?\+-=\\\.&]*)"
                },
                PropertyName = PropertyName
            };
            ModelContext.GetSettings(PropertyName).ValidationSettings.Add(RunConfiguration(configuration, rule));
            return this;
        }

        public StringRulesConfiguration<TModel> Email(Action<RuleInitializer<TModel, string>> configuration = null)
        {
            var rule = new ValidationSetting<TModel>
            {
                Rule = new RegExValidator { Pattern = @"[\w\d!#$%&'*+-/=?^`{|}~]+(\.[\w\d!#$%&'*+-/=?^`{|}~]+)*@([a-z\d][-a-z\d]*[a-z\d]\.)*[a-z][-a-z\d]*[a-z]" },
                PropertyName = PropertyName
            };
            ModelContext.GetSettings(PropertyName).ValidationSettings.Add(RunConfiguration(configuration, rule));
            return this;
        }

        public StringRulesConfiguration<TModel> RegEx(string pattern, Action<RuleInitializer<TModel, string>> configuration = null)
        {
            var rule = new ValidationSetting<TModel>
            {
                Rule = new RegExValidator { Pattern = pattern },
                PropertyName = PropertyName
            };
            ModelContext.GetSettings(PropertyName).ValidationSettings.Add(RunConfiguration(configuration, rule));
            return this;
        }
    }
}